package cn.zfs.springcloud.datasource.aspect;

import cn.zfs.springcloud.datasource.annotation.ManagementTransaction;
import cn.zfs.springcloud.datasource.contextholder.DataSourceContextHolder;
import cn.zfs.springcloud.datasource.init.InitData;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 事务管理
 */
@SuppressWarnings({"ReflectionForUnavailableAnnotation", "SpringAutowiredFieldsWarningInspection"})
@Aspect
@Component
@Order(3)
public class ManagementTransactionAspect {

    private Logger logger = LoggerFactory.getLogger(ManagementTransactionAspect.class);

    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private AspectPublic aspectPublic;
    @Autowired
    private InitData initData;

    @Pointcut("@annotation(cn.zfs.springcloud.datasource.annotation.ManagementTransaction)")
    public void managementTransactionPointcut() {
    }

    @Before("managementTransactionPointcut()")
    public void before(JoinPoint point) {
        Class<?> clazz = point.getTarget().getClass(); //获得当前访问的class
        String methodName = point.getSignature().getName(); //获得当前访问的方法名
        Class[] argClass = ((MethodSignature) point.getSignature()).getParameterTypes();//获得当前方法的参数的类型
        try {
            Method method = clazz.getMethod(methodName, argClass);//获得当前访问的方法对象
            logger.debug("判断是否存在@ManagementTransaction");
            if (method.isAnnotationPresent(ManagementTransaction.class)) {
                ManagementTransaction managementTransaction = method.getAnnotation(ManagementTransaction.class);
                aspectPublic.openTransaction(applicationContext, DataSourceContextHolder.getDetermineCurrentLookupKey(),
                        managementTransaction.openTransaction(), managementTransaction.openTransactionNum(),
                        managementTransaction.thisMethodOpenTransaction());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @AfterReturning("managementTransactionPointcut()")
    public void afterReturning() {
        aspectPublic.commitTransactionClearThreadLocal();
    }

    @AfterThrowing(pointcut = "managementTransactionPointcut()", throwing = "ex")
    public void afterThrowing(Throwable ex) throws Throwable {
        logger.error("出现异常", ex);
        aspectPublic.rollbackTransaction();
        aspectPublic.clearThreadLocal();
    }
}
